#include "string.h"
#include <algorithm>
#include <cstddef>
#include <cstring>

namespace xywl {
    const size_t string::npos = -1;
    void string::reserve(size_t n){
        if(n > _capacity) {
            char* temp = new char[n + 1]; //  这里要预留一个位置给'\0'
            strcpy(temp, _str);
            delete[] _str;
            _str = temp;
            _capacity = n;
        }
    }
    void string::push_back(char ch){
        if(_size == _capacity) {
            reserve(_capacity == 0 ? _capacity = 4 : _capacity * 2);
        }
        _str[_size++] = ch;
        _str[_size] = '\0';
    }
    void string::append(const char* str) {
        size_t len = strlen(str);
        if(_size + len > _capacity) {
            reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
        }
        strcpy(_str + _size, str);
        _size += len;
    }
    string& string::operator+=(char ch) {
        push_back(ch);
        return *this;
    }
    string& string::operator+=(const char* str) {
        append(str);
        return *this;
    }
    void string::insert(size_t pos, char ch) {
        assert(pos <= _size);
        if(_size == _capacity) {
            reserve(_capacity == 0 ? _capacity = 4 : _capacity * 2);
        }
        size_t len = _size + 1;
        while(len > pos) {
            _str[len] = _str[len - 1];
            len--;
        }
        _str[pos] = ch;
        _size++;
    }
    void string::insert(size_t pos, const char* str) {
        assert(pos <= _size);
        size_t len = strlen(str);
        if(_size + len > _capacity) // 这里没有必要写等于，因为等于的时候是可以正好放进去的，提前开了一个位置放入'\0'
        {
            reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
        }
        size_t end = _size + len;
        while(end > pos + len - 1) // 这个地方要减1才行，实在是无法理解可以画图或是根据上面push_back一个长度的字符串没有+1间记
        {
            _str[end] = _str[end - len];
            end--;
        }
        for(size_t i = 0; i < len; i++) {
            _str[pos + i] = str[i];
        }
        _size += len;
    }
    void string::erase(size_t pos, size_t len) {
        assert(pos < _size); // 这里和上面的不一样要注意，_size位置没得删
        if(len >= _size - pos) {
            _str[pos] = '\0';
            _size = pos;
        }else {
            for(size_t i = pos + len; i <= _size; i++) {
                _str[i - len] = _str[i]; 
            }
            _size -= len;
        }
    }
    size_t string::find(char ch, size_t pos) {
        assert(pos < _size);
        for(int i = pos; i < _size; i++) {
            if(_str[i] == ch) {
                return i;
            }
        }
        return npos;
    }
    size_t string::find(const char* str, size_t pos) {
        assert(pos < _size);
        const char* p = strstr(_str + pos, str);
        if(p == nullptr) {
            return npos;
        }else {
            return p - _str;
        }
    }
    string string::substr(size_t pos, size_t len) {
        assert(pos < _size);
        if(len > _size - pos) {
            len = _size - pos;
        }
        string temp;
        temp.reserve(len);
        for(int i = 0; i < len; i++) {
            //temp[i] = _str[pos + i]; // 这样写不安全
            temp += _str[pos + i];
        }
        return temp;
    }
    bool operator<(const string& s1, const string& s2) {
        return strcmp(s1.c_str(), s2.c_str()) < 0;
    }
    bool operator<=(const string& s1, const string& s2) {
        return s1 < s2 || s1 == s2;
    }
    bool operator>(const string& s1, const string& s2) {
        return !(s1 <= s2);
    }
    bool operator>=(const string& s1, const string& s2) {
        return !(s1 < s2);
    }
    bool operator==(const string& s1, const string& s2) {
        return strcmp(s1.c_str(), s2.c_str()) == 0;
    }
    bool operator!=(const string& s1, const string& s2) {
        return !(s1 == s2);
    }

    ostream& operator<<(ostream& out, const string& s) {
        for(auto c : s) {
            out << c;
        }
        return out;
    }
    istream& operator>>(istream& in, string& s) {
        s.clear();
        const int N = 256;
        char buffer[N];
        int i = 0;
        char c;
        c = in.get();
        while(c != ' ' && c != '\n') {
            buffer[i++] = c;
            if(i == N - 1) {
                buffer[i] = '\0';
                s += buffer;
                i = 0;
            }
            c = in.get();
        }
        if(i > 0) {
            buffer[i] = '\0';
            s += buffer;
        }
        return in;
    }
}